package com.open.capacity.salary.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.open.capacity.commons.CodeEnum;
import com.open.capacity.commons.PageResult;
import com.open.capacity.salary.constant.Globals;
import com.open.capacity.salary.dao.GzReportDao;
import com.open.capacity.salary.entity.GzItem;
import com.open.capacity.salary.entity.GzZtUser;
import com.open.capacity.salary.service.*;
import com.open.capacity.utils.BigDecimalUtil;
import com.open.capacity.utils.CollectionUtil;
import com.open.capacity.utils.DateUtil;
import com.open.capacity.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class GzReportServiceImpl implements GzReportService {

    @Autowired
    private GzReportDao gzReportDao;

    @Autowired
    private GzItemService gzItemService;

    @Autowired
    private GzZtUserService ztUserService;

    @Autowired
    private GzEnableMonthService gzEnableMonthService;

    /**
     * 工资查询
     *
     * @param params
     * @return
     */
    public List<Map<String, Object>> findAll(Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String monthStart = params.get("monthStart").toString();
        String monthEnd = params.get("monthEnd").toString();
        if (monthStart.equals(monthEnd) || StringUtil.isEmpty(monthEnd)) {
            params.put("month", monthStart);
        } else {
            params.put("monthStart", monthStart);
            params.put("monthEnd", monthEnd);
        }

        String ztId = params.get("ztId").toString();
        String[] ztIds = ztId.split(",");
        List<String> itemList = gzItemService.findByZtIds(companyId, ztId);
        params.put("itemColumns", itemList);
        params.put("ztId", Arrays.asList(ztId.split(",")));
        if (params.containsKey("departmentId") && StringUtil.isNotEmpty(params.get("departmentId").toString())) {
            String departmentId = params.get("departmentId").toString();
            params.put("departmentId", Arrays.asList(departmentId.split(",")));
        } else {
            params.remove("departmentId");
        }
        if (params.containsKey("departmentName") && StringUtil.isNotEmpty(params.get("departmentName").toString())) {
            String departmentName = params.get("departmentName").toString();
            params.put("departmentName", Arrays.asList(departmentName.split(",")));
        } else {
            params.remove("departmentName");
        }
        if (params.containsKey("userCategory") && StringUtil.isNotEmpty(params.get("userCategory").toString())) {
            String userCategory = params.get("userCategory").toString();
            params.put("userCategory", Arrays.asList(userCategory.split(",")));
        } else {
            params.remove("userCategory");
        }

        List<Map<String, Object>> mapList = new ArrayList<>();

        //判断是否从历史表中查询数据
        String maxMonth = DateUtil.getMonth(DateUtil.formatDate(new Date()), "yyyy-MM", -1 * (Globals.GZDATA_SAVE_MONTH - 1));
        if (monthEnd.compareTo(maxMonth) < 0) { //全部从历史表取数
            mapList = gzReportDao.findAllHistory(params);
        } else if (monthStart.compareTo(maxMonth) >= 0) { //全部从最新表取数
            mapList = gzReportDao.findAllNew(params);
        } else {
            mapList = gzReportDao.findAllHistory(params);
            mapList.addAll(gzReportDao.findAllNew(params));
        }

        String ignoreUsername = params.containsKey("ignoreUsername") ? params.get("ignoreUsername").toString() : "";
        String currentMonth = gzEnableMonthService.findByZtId(companyId, ztIds[0]).getCurrentMonth();

        List<String> ignoreUserList = Arrays.asList(ignoreUsername.split(","));
        List<GzZtUser> ztUsers = new ArrayList<>();
        for (String zt : ztIds) {
            ztUsers.addAll(ztUserService.findByZtId(companyId, zt));
        }

        for (int i = 0; i < mapList.size(); i++)
            for (Map.Entry<String, Object> entry : mapList.get(i).entrySet()) {
                if (currentMonth.equals(monthStart)) {
                    if (entry.getKey().equals("userid")) {
                        String userId = entry.getValue().toString();
//                    if (mapList.get(i).size() < 7 && ztUsers.stream().filter(t -> t.getUserId().equals(userId)).count() == 0) {
                        if (ztUsers.stream().filter(t -> t.getUserId().equals(userId)).count() == 0) {
                            mapList.remove(i);
                            i--;
                        }
                    }
                }
                if (StringUtil.isNotEmpty(ignoreUsername) && entry.getKey().equals("username")) {
                    if (ignoreUserList.contains(entry.getValue().toString())) {
                        mapList.remove(i);
                        i--;
                    }
                }
            }

        return mapList;
    }

    @Override
    public List<Map<String, Object>> findByUser(Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String monthStart = params.get("monthStart").toString();
        String monthEnd = params.get("monthEnd").toString();
        params.put("monthStart", monthStart);
        params.put("monthEnd", monthEnd);
        String ztId = params.get("ztId").toString();
        List<String> itemList = gzItemService.findByZtIds(companyId, ztId);
        params.put("itemColumns", itemList);

        params.put("ztId", Arrays.asList(ztId.split(",")));

        String sidx = params.get("sidx").toString();
        String sord = params.get("sord").toString();
        if (StringUtil.isNotEmpty(sidx) && StringUtil.isNotEmpty(sord)) {
            params.put("orderby", sidx + " " + sord);
        }
        if (params.containsKey("departmentId") && StringUtil.isNotEmpty(params.get("departmentId").toString())) {
            String departmentId = params.get("departmentId").toString();
            params.put("departmentId", Arrays.asList(departmentId.split(",")));
        } else {
            params.remove("departmentId");
        }
        if (params.containsKey("departmentName") && StringUtil.isNotEmpty(params.get("departmentName").toString())) {
            String departmentName = params.get("departmentName").toString();
            params.put("departmentName", Arrays.asList(departmentName.split(",")));
        } else {
            params.remove("departmentName");
        }
        if (params.containsKey("userCategory") && StringUtil.isNotEmpty(params.get("userCategory").toString())) {
            String userCategory = params.get("userCategory").toString();
            params.put("userCategory", Arrays.asList(userCategory.split(",")));
        } else {
            params.remove("userCategory");
        }

        List<Map<String, Object>> list = new ArrayList<>();
        String maxMonth = DateUtil.getMonth(DateUtil.formatDate(new Date()), "yyyy-MM", -1 * (Globals.GZDATA_SAVE_MONTH - 1));
        if (monthEnd.compareTo(maxMonth) < 0) { //历史别
            list = gzReportDao.findByUserHistory(params);
        } else if (monthStart.compareTo(maxMonth) >= 0) { //全部从最新表取数
            list = gzReportDao.findByUserNew(params);
        } else {
            list = gzReportDao.findByUserAll(params);
        }

        if (monthEnd.compareTo(monthStart) > 0) {
            List<Map<String, Object>> newList = packetUserGroup(list);
            list.addAll(newList);
        }
        Collections.sort(list, (o1, o2) -> {
            String userCode1 = o1.get("usercode").toString();
            String userCode2 = o2.get("usercode").toString();
            String month1 = !o1.containsKey("month") ? "3099-12" : o1.get("month").toString();
            String month2 = !o2.containsKey("month") ? "3099-12" : o2.get("month").toString();
            if (userCode1.compareTo(userCode2) > 0) {
                return 1;
            } else if (userCode1.compareTo(userCode2) < 0) {
                return -1;
            } else if (month1.compareTo(month2) > 0) {
                return 1;
            } else if (month1.compareTo(month2) < 0) {
                return -1;
            } else {
                return 0;
            }
        });

        return list;
    }

    /**
     * 个人明细
     *
     * @param params
     * @return
     */
    public PageResult<Map<String, Object>> pageByUser(Map<String, Object> params) {
        String companyId = params.get("companyId").toString();
        String monthStart = params.get("monthStart").toString();
        String monthEnd = params.get("monthEnd").toString();
        params.put("monthStart", monthStart);
        params.put("monthEnd", monthEnd);
        String ztId = params.get("ztId").toString();
        List<String> itemList = gzItemService.findByZtIds(companyId, ztId);
        params.put("itemColumns", itemList);

        params.put("ztId", Arrays.asList(ztId.split(",")));
        //设置分页信息，分别是当前页数和每页显示的总记录数【记住：必须在mapper接口中的方法执行之前设置该分页信息】
        if (MapUtils.getInteger(params, "page") != null && MapUtils.getInteger(params, "limit") != null)
            PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);

        String sidx = params.get("sidx").toString();
        String sord = params.get("sord").toString();
        if (StringUtil.isNotEmpty(sidx) && StringUtil.isNotEmpty(sord)) {
            params.put("orderby", sidx + " " + sord);
        }
        if (params.containsKey("departmentId") && StringUtil.isNotEmpty(params.get("departmentId").toString())) {
            String departmentId = params.get("departmentId").toString();
            params.put("departmentId", Arrays.asList(departmentId.split(",")));
        } else {
            params.remove("departmentId");
        }
        if (params.containsKey("departmentName") && StringUtil.isNotEmpty(params.get("departmentName").toString())) {
            String departmentName = params.get("departmentName").toString();
            params.put("departmentName", Arrays.asList(departmentName.split(",")));
        } else {
            params.remove("departmentName");
        }
        if (params.containsKey("userCategory") && StringUtil.isNotEmpty(params.get("userCategory").toString())) {
            String userCategory = params.get("userCategory").toString();
            params.put("userCategory", Arrays.asList(userCategory.split(",")));
        } else {
            params.remove("userCategory");
        }
        List<Map<String, Object>> list = new ArrayList<>();
        String maxMonth = DateUtil.getMonth(DateUtil.formatDate(new Date()), "yyyy-MM", -1 * (Globals.GZDATA_SAVE_MONTH - 1));
        if (monthEnd.compareTo(maxMonth) < 0) { //历史别
            list = gzReportDao.findByUserHistory(params);
        } else if (monthStart.compareTo(maxMonth) >= 0) { //全部从最新表取数
            list = gzReportDao.findByUserNew(params);
        } else {
            list = gzReportDao.findByUserAll(params);
        }

        if (monthEnd.compareTo(monthStart) > 0) {
            List<Map<String, Object>> newList = packetUserGroup(list);
            list.addAll(newList);
        }
        Collections.sort(list, (o1, o2) -> {
            String userCode1 = o1.get("usercode").toString();
            String userCode2 = o2.get("usercode").toString();
            String month1 = o1.get("month") == null ? "" : o1.get("month").toString();
            String month2 = o2.get("month") == null ? "" : o2.get("month").toString();
            if (userCode1.compareTo(userCode2) > 0) {
                return 1;
            } else if (userCode1.compareTo(userCode2) < 0) {
                return -1;
            } else if (month1.compareTo(month2) > 0) {
                return 1;
            } else if (month1.compareTo(month2) < 0) {
                return -1;
            } else {
                return 0;
            }
        });
        PageInfo<Map<String, Object>> pageInfo = new PageInfo(list);

        return PageResult.<Map<String, Object>>builder().data(pageInfo.getList()).resp_code(CodeEnum.SUCCESS.getCode()).count(pageInfo.getTotal()).build();
    }

    //个人合计
    private List<Map<String, Object>> packetUserGroup(List<Map<String, Object>> list) {
        List<Map<String, Object>> temp = CollectionUtil.deepCopy(list);
        // 接收处理后的数据
        List<Map<String, Object>> newMapVOs = new ArrayList<>();
        // 数据分组统计处理
        temp.parallelStream()
                .collect(Collectors.groupingBy(item -> (item.get("departmentname").toString() + item.get("username").toString()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer.stream()
                            .reduce((a, b) -> {
                                        Map<String, Object> c = new HashMap();
                                        for (Map.Entry<String, Object> entry1 : a.entrySet()) {
                                            c.put(entry1.getKey(), entry1.getValue());
                                        }

                                        for (Map.Entry<String, Object> entry2 : b.entrySet()) {
                                            if (entry2.getKey().equals("departmentname") || entry2.getKey().equals("departmentid") ||
                                                    entry2.getKey().equals("userid") || entry2.getKey().equals("usercode") ||
                                                    entry2.getKey().equals("code") ||
                                                    entry2.getKey().equals("username") || entry2.getKey().equals("month")) {
                                                continue;
                                            }
                                            if (c.keySet().contains(entry2.getKey())) {
                                                c.put(entry2.getKey(), (new BigDecimal(c.get(entry2.getKey()).toString())).add(new BigDecimal(entry2.getValue().toString())));
                                            }
                                        }
                                        return c;
                                    }
                            )
                            .ifPresent(newMapVOs::add);
                });

        for (Map<String, Object> item : newMapVOs) {
            item.put("month", "合计：");
        }
        return newMapVOs;

    }
}
